using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web;
using BBX.Common;
using BBX.Entity;
using BBX.Forum;
using NewLife.Xml;
using System.Linq;
using XUser = BBX.Entity.User;

namespace BBX.Web
{
    public class stats : PageBase
    {
        public Hashtable totalstats = new Hashtable();
        public Hashtable osstats = new Hashtable();
        public Hashtable browserstats = new Hashtable();
        public Hashtable monthstats = new Hashtable();
        public Hashtable weekstats = new Hashtable();
        public Hashtable hourstats = new Hashtable();
        public Dictionary<String, String> mainstats = new Dictionary<String, String>();
        public Hashtable daypostsstats = new Hashtable();
        public Hashtable monthpostsstats = new Hashtable();
        public Hashtable forumsrankstats = new Hashtable();
        public Hashtable onlinesstats = new Hashtable();
        public Hashtable postsrankstats = new Hashtable();
        public Hashtable teamstats = new Hashtable();
        public Hashtable creditsrankstats = new Hashtable();
        public Hashtable tradestats = new Hashtable();
        public String lastupdate = "";
        public String nextupdate = "";
        public String type = "";
        public String statuspara = "";
        public String primarybegin = (String.IsNullOrEmpty(DNTRequest.GetString("primarybegin"))) ? DateTime.Now.AddMonths(-1).AddDays(1.0).ToString("yyyy-MM-dd") : DNTRequest.GetString("primarybegin");
        public String primaryend = (String.IsNullOrEmpty(DNTRequest.GetString("primaryend"))) ? DateTime.Now.ToString("yyyy-MM-dd") : DNTRequest.GetString("primaryend");
        public Int32 members;
        public Int32 mempost;
        public String admins;
        public Int32 memnonpost;
        public String lastmember;
        public Double mempostpercent;
        public String bestmem;
        public Int32 bestmemposts;
        public Int32 forums;
        public Double mempostavg;
        public Double postsaddavg;
        public Double membersaddavg;
        public Double topicreplyavg;
        public Double pageviewavg;
        public IXForum hotforum;
        public Int32 topics;
        public Int32 posts;
        public String postsaddtoday;
        public String membersaddtoday;
        public String activeindex;
        public Boolean statstatus;
        public String monthpostsofstatsbar = "";
        public String daypostsofstatsbar = "";
        public String monthofstatsbar = "";
        public Int32 runtime;
        public String weekofstatsbar = string.Empty;
        public String hourofstatsbar = string.Empty;
        public String browserofstatsbar = string.Empty;
        public String osofstatsbar = string.Empty;
        public String hotreplytopics;
        public String hottopics;
        public String postsrank;
        public String digestpostsrank;
        public String thismonthpostsrank;
        public String todaypostsrank;
        public String topicsforumsrank;
        public String postsforumsrank;
        public String thismonthforumsrank;
        public String todayforumsrank;
        public String[] score;
        public String creditsrank;
        public String extcreditsrank1;
        public String extcreditsrank2;
        public String extcreditsrank3;
        public String extcreditsrank4;
        public String extcreditsrank5;
        public String extcreditsrank6;
        public String extcreditsrank7;
        public String extcreditsrank8;
        public String totalonlinerank;
        public String thismonthonlinerank;
        public Int32 maxos;
        public Int32 maxbrowser;
        public Int32 maxmonth;
        public Int32 yearofmaxmonth;
        public Int32 monthofmaxmonth;
        public Int32 maxweek;
        public String dayofmaxweek;
        public Int32 maxhour;
        public Int32 maxhourfrom;
        public Int32 maxhourto;
        public Int32 maxmonthposts;
        public Int32 maxdayposts;
        public Int32 statscachelife = 120;
        private Dictionary<String, String> statvars = new Dictionary<String, String>();
        public Boolean needlogin;

        protected override void ShowPage()
        {
            pagetitle = "统计";
            if (!usergroupinfo.AllowViewstats && (!(DNTRequest.GetString("type") == "trend") || !(DNTRequest.GetString("xml") == "1")))
            {
                base.AddErrLine("您所在的用户组 ( <b>" + usergroupinfo.GroupTitle + "</b> ) 没有查看统计信息的权限");
                needlogin = (userid < 1);
                return;
            }
            statscachelife = ((statscachelife <= 0) ? statscachelife : config.Statscachelife);

            var allStats = Stat.GetAll();
            statstatus = config.Statstatus;
            totalstats["hits"] = 0;
            totalstats["maxmonth"] = 0;
            totalstats["guests"] = 0;
            totalstats["visitors"] = 0;
            foreach (var item in allStats)
            {
                String a;
                if ((a = item.Type) != null)
                {
                    if (!(a == "total"))
                    {
                        if (!(a == "os"))
                        {
                            if (!(a == "browser"))
                            {
                                if (!(a == "month"))
                                {
                                    if (!(a == "week"))
                                    {
                                        if (a == "hour")
                                        {
                                            SetValue(item, hourstats);
                                            if (item.Count > maxhour)
                                            {
                                                maxhour = item.Count;
                                                maxhourfrom = item.Variable.ToInt(0);
                                                maxhourto = maxhourfrom + 1;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        SetValue(item, weekstats);
                                        if (item.Count > maxweek)
                                        {
                                            maxweek = item.Count;
                                            dayofmaxweek = item.Variable;
                                        }
                                    }
                                }
                                else
                                {
                                    SetValue(item, monthstats);
                                    if (item.Count > maxmonth)
                                    {
                                        maxmonth = item.Count;
                                        yearofmaxmonth = item.Variable.ToInt(0) / 100;
                                        monthofmaxmonth = item.Variable.ToInt(0) - yearofmaxmonth * 100;
                                    }
                                }
                            }
                            else
                            {
                                SetValue(item, browserstats);
                                maxbrowser = ((item.Count > maxbrowser) ? item.Count : maxbrowser);
                            }
                        }
                        else
                        {
                            SetValue(item, osstats);
                            maxos = ((item.Count > maxos) ? item.Count : maxos);
                        }
                    }
                    else
                    {
                        SetValue(item, totalstats);
                    }
                }
            }
            //List<StatVarInfo> allStatVars = Stats.GetAllStatVars();
            //var allStatVars = StatVar.GetAll();
            foreach (var item in StatVar.GetAll())
            {
                if ((item.Variable != "lastupdate" || !Utils.IsNumeric(item.Value)) && item.Type != null)
                {
                    switch (item.Type)
                    {
                        case "dayposts":
                            SetValue(item, daypostsstats);
                            break;

                        case "creditsrank":
                            SetValue(item, creditsrankstats);
                            break;

                        case "forumsrank":
                            SetValue(item, forumsrankstats);
                            break;

                        case "postsrank":
                            SetValue(item, postsrankstats);
                            break;

                        case "main":
                            //this.SetValue(item, this.mainstats);
                            mainstats[item.Variable] = item.Value;
                            break;

                        case "monthposts":
                            SetValue(item, monthpostsstats);
                            break;

                        case "onlines":
                            SetValue(item, onlinesstats);
                            break;

                        case "team":
                            SetValue(item, teamstats);
                            break;

                        case "trade":
                            SetValue(item, tradestats);
                            break;
                    }
                }
            }
            type = DNTRequest.GetString("type");
            if ((String.IsNullOrEmpty(type) && !statstatus) || type == "posts")
            {
                StatVar.DeleteOldDayposts();
                monthpostsstats = Stats.GetMonthPostsStats(monthpostsstats);
                maxmonthposts = (Int32)monthpostsstats["maxcount"];
                monthpostsstats.Remove("maxcount");
                daypostsstats = Stats.GetDayPostsStats(daypostsstats);
                maxdayposts = (Int32)daypostsstats["maxcount"];
                daypostsstats.Remove("maxcount");
            }
            String key2;
            switch (key2 = type)
            {
                case "views":
                    GetViews();
                    return;

                case "client":
                    GetClient();
                    return;

                case "posts":
                    GetPosts();
                    return;

                case "forumsrank":
                    GetForumsRank();
                    return;

                case "topicsrank":
                    GetTopicsRank();
                    return;

                case "postsrank":
                    GetPostsRank();
                    return;

                case "creditsrank":
                    GetCreditsRank();
                    return;

                case "trade":
                    GetTrade();
                    return;

                case "onlinetime":
                    GetOnlinetime();
                    return;

                case "team":
                    GetTeam();
                    return;

                case "modworks":
                    GetModWorks();
                    return;

                case "trend":
                    GetTrend();
                    return;

                case "":
                    Default();
                    return;
            }
            base.AddErrLine("未定义操作请返回");
            base.SetShowBackLink(false);
        }

        private void GetTrend()
        {
            var text = Utils.MD5(config.Passwordkey + "\t" + DateTime.Now.Day);
            if (text != DNTRequest.GetString("hash") && DNTRequest.GetString("xml") != "")
            {
                base.AddErrLine("参数验证不正确");
                return;
            }
            if (!Utils.IsDateString(primarybegin))
            {
                base.AddErrLine("起始日期格式不正确");
                return;
            }
            if (!Utils.IsDateString(primaryend))
            {
                base.AddErrLine("结束日期格式不正确");
                return;
            }
            var text2 = (String.IsNullOrEmpty(DNTRequest.GetString("types"))) ? "all" : DNTRequest.GetString("types");
            var text3 = (text2 == "all") ? "login,register,topic,poll,bonus,debate,post" : text2;
            var array = text3.Split(',');
            for (var i = 0; i < array.Length; i++)
            {
                var str = array[i];
                if (!Utils.InArray(str, "all,login,register,topic,poll,bonus,debate,post"))
                {
                    base.AddErrLine("参数验证不正确");
                    return;
                }
            }
            var t = primarybegin.ToDateTime(DateTime.Now.AddMonths(-1).AddDays(1.0));
            var t2 = primaryend.ToDateTime();
            if (t > t2)
            {
                base.AddErrLine("统计开始日期不能小于结束日期");
                return;
            }
            primarybegin = t.ToString("yyyy-MM-dd");
            primaryend = t2.ToString("yyyy-MM-dd");
            if (DNTRequest.GetString("xml") != "")
            {
                var hashtable = new Hashtable();
                var field = "*";
                if (DNTRequest.GetString("merge") == "1")
                {
                    field = "[daytime],[" + text3.Replace(",", "]+[") + "] AS [statistic]";
                    text3 = "statistic";
                }
                var hashtable2 = new Hashtable();
                hashtable2.Add("login", "登录用户");
                hashtable2.Add("register", "新注册用户");
                hashtable2.Add("topic", "主题");
                hashtable2.Add("poll", "投票");
                hashtable2.Add("bonus", "悬赏");
                hashtable2.Add("debate", "辩论");
                hashtable2.Add("post", "主题回帖");
                var trendGraph = Stats.GetTrendGraph(hashtable, field, t.ToString("yyyyMMdd"), t2.ToString("yyyyMMdd"), text3);
                var stringBuilder = new StringBuilder(2048);
                stringBuilder.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
                stringBuilder.AppendFormat("<chart><xaxis>{0}</xaxis><graphs>", trendGraph);
                var num = 0;
                foreach (String key in hashtable.Keys)
                {
                    stringBuilder.AppendFormat("<graph gid=\"{0}\" title=\"{1}\">{2}</graph>", num, hashtable2[key], hashtable[key]);
                    num++;
                }
                stringBuilder.Append("</graphs></chart>");
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.Expires = -1;
                HttpContext.Current.Response.ContentType = "application/xml";
                HttpContext.Current.Response.Write(stringBuilder.ToString());
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                return;
            }
            statuspara = "path=&settings_file=config/stat_setting.xml&data_file=" + Utils.UrlEncode("stats.aspx?type=trend&xml=1&types=" + text2 + "&primarybegin=" + primarybegin + "&primaryend=" + primaryend + "&merge=" + DNTRequest.GetInt("merge", 0) + "&hash=" + text);
        }

        private void SetValue(Stat stat, Hashtable ht)
        {
            ht[stat.Variable] = stat.Count;
        }

        private void SetValue(StatVar statvar, Hashtable ht)
        {
            ht[statvar.Variable] = statvar.Value;
        }

        void CheckLastUpdate(String type)
        {
            if (!statvars.ContainsKey("lastupdate") || (DateTime.Now - statvars["lastupdate"].ToDateTime()).TotalMinutes > (Double)statscachelife)
            {
                var now = DateTime.Now.ToFullString();
                statvars.Clear();
                statvars["lastupdate"] = now;
                StatVar.Update(type, "lastupdate", now);
            }
        }

        private void Default()
        {
            lastmember = Statistic.Current.LastUserName;
            foreach (var item in mainstats)
            {
                statvars[item.Key] = item.Value;
            }
            CheckLastUpdate("main");
            forums = XForum.GetForumCount();
            var st = Statistic.Current;
            topics = st.TotalTopic;
            posts = st.TotalPost;
            members = st.TotalUsers;
            if (statvars.ContainsKey("runtime"))
            {
                runtime = statvars["runtime"].ToInt(0);
            }
            else
            {
                runtime = (DateTime.Now - Convert.ToDateTime(monthpostsstats["starttime"])).Days;
                StatVar.Update("main", "runtime", runtime);
            }
            if (statvars.ContainsKey("postsaddtoday"))
            {
                postsaddtoday = statvars["postsaddtoday"];
            }
            else
            {
                postsaddtoday = Post.GetTodayPostCount(0).ToString();
                StatVar.Update("main", "postsaddtoday", postsaddtoday);
            }
            if (statvars.ContainsKey("membersaddtoday"))
            {
                membersaddtoday = statvars["membersaddtoday"];
            }
            else
            {
                membersaddtoday = BBX.Entity.User.GetTodayNewMemberCount().ToString();
                StatVar.Update("main", "membersaddtoday", membersaddtoday);
            }
            if (statvars.ContainsKey("admins"))
            {
                admins = statvars["admins"];
            }
            else
            {
                admins = BBX.Entity.User.GetAdminCount().ToString();
                StatVar.Update("main", "admins", admins);
            }
            if (statvars.ContainsKey("memnonpost"))
            {
                memnonpost = statvars["memnonpost"].ToInt(0);
            }
            else
            {
                memnonpost = BBX.Entity.User.GetNonPostMemCount();
                StatVar.Update("main", "memnonpost", memnonpost);
            }
            if (statvars.ContainsKey("hotforum"))
            {
                hotforum = XForum.FindByID(statvars["hotforum"].ToInt());
            }
            else
            {
                hotforum = Stats.GetHotForum();
                StatVar.Update("main", "hotforum", hotforum.ID + "");
            }
            if (statvars.ContainsKey("bestmem") && statvars.ContainsKey("bestmemposts"))
            {
                bestmem = statvars["bestmem"];
                bestmemposts = statvars["bestmemposts"].ToInt(0);
            }
            else
            {
                Post.GetBestMember(out bestmem, out bestmemposts);
                StatVar.Update("main", "bestmem", bestmem);
                StatVar.Update("main", "bestmemposts", bestmemposts);
            }
            mempost = members - memnonpost;
            mempostavg = Math.Round((Double)posts / (Double)members, 2);
            topicreplyavg = Math.Round((Double)(posts - topics) / (Double)topics, 2);
            mempostpercent = Math.Round((Double)(mempost * 100) / (Double)members, 2);
            postsaddavg = Math.Round((Double)posts / (Double)runtime, 2);
            membersaddavg = (Double)(members / runtime);
            var num = totalstats["members"].ToInt() + totalstats["guests"].ToInt();
            totalstats["visitors"] = num;
            pageviewavg = Math.Round((Double)totalstats["hits"].ToInt() / (Double)((num == 0) ? 1 : num), 2);
            activeindex = ((Math.Round(membersaddavg / (Double)((members == 0) ? 1 : members), 2) + Math.Round(postsaddavg / (Double)((posts == 0) ? 1 : posts), 2)) * 1500.0 + topicreplyavg * 10.0 + mempostavg + Math.Round(mempostpercent / 10.0, 2) + pageviewavg).ToString();
            if (statstatus)
            {
                monthofstatsbar = Stats.GetStatsDataHtml("month", monthstats, maxmonth);
            }
            else
            {
                monthpostsofstatsbar = Stats.GetStatsDataHtml("monthposts", monthpostsstats, maxmonthposts);
                daypostsofstatsbar = Stats.GetStatsDataHtml("dayposts", daypostsstats, maxdayposts);
            }
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetModWorks() { }

        private void GetTeam()
        {
            foreach (String key in teamstats.Keys)
            {
                statvars[key] = teamstats[key] + "";
            }
            CheckLastUpdate("team");
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetOnlinetime()
        {
            if (config.Oltimespan == 0)
            {
                totalonlinerank = "<li>未开启在线时长统计</li>";
                thismonthonlinerank = "<li></li>";
                return;
            }
            foreach (String key in onlinesstats.Keys)
            {
                statvars[key] = onlinesstats[key] + "";
            }
            CheckLastUpdate("onlines");
            var total = Stats.GetUserOnline(statvars, "total");
            var thismonth = Stats.GetUserOnline(statvars, "thismonth");
            var maxrows = Math.Max(total.Length, thismonth.Length);
            totalonlinerank = Stats.GetUserRankHtml(total, "onlinetime", maxrows);
            thismonthonlinerank = Stats.GetUserRankHtml(thismonth, "onlinetime", maxrows);
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetTrade() { }

        private void GetCreditsRank()
        {
            score = Scoresets.GetValidScoreName();
            foreach (String key in creditsrankstats.Keys)
            {
                statvars[key] = creditsrankstats[key] + "";
            }
            CheckLastUpdate("creditsrank");
            var credits = Stats.GetCreditsRank(statvars, "credits");
            var extendedcredits = Stats.GetExtCreditsRank(statvars, "extendedcredits");
            var num = credits.Length;
            for (var i = 1; i < 8; i++)
            {
                num = Math.Max(extendedcredits[i].Length, num);
            }
            creditsrank = Stats.GetUserRankHtml(credits, "credits", num);
            extcreditsrank1 = Stats.GetUserRankHtml(extendedcredits[0], "extcredits1", num);
            extcreditsrank2 = Stats.GetUserRankHtml(extendedcredits[1], "extcredits2", num);
            extcreditsrank3 = Stats.GetUserRankHtml(extendedcredits[2], "extcredits3", num);
            extcreditsrank4 = Stats.GetUserRankHtml(extendedcredits[3], "extcredits4", num);
            extcreditsrank5 = Stats.GetUserRankHtml(extendedcredits[4], "extcredits5", num);
            extcreditsrank6 = Stats.GetUserRankHtml(extendedcredits[5], "extcredits6", num);
            extcreditsrank7 = Stats.GetUserRankHtml(extendedcredits[6], "extcredits7", num);
            extcreditsrank8 = Stats.GetUserRankHtml(extendedcredits[7], "extcredits8", num);
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetPostsRank()
        {
            foreach (String key in postsrankstats.Keys)
            {
                statvars[key] = postsrankstats[key] + "";
            }
            CheckLastUpdate("postsrank");
            XUser[] array;
            if (statvars.ContainsKey("posts"))
            {
                array = statvars["posts"].ToXmlEntity<XUser[]>();
            }
            else
            {
                array = Stats.GetUserArray("posts");
                StatVar.Update("postsrank", "posts", array.ToXml());
            }
            XUser[] array2;
            if (statvars.ContainsKey("digestposts"))
            {
                array2 = statvars["digestposts"].ToXmlEntity<XUser[]>();
            }
            else
            {
                array2 = Stats.GetUserArray("digestposts");
                StatVar.Update("postsrank", "digestposts", array2.ToXml());
            }
            XUser[] array3;
            if (statvars.ContainsKey("thismonth"))
            {
                array3 = statvars["thismonth"].ToXmlEntity<XUser[]>();
            }
            else
            {
                array3 = Stats.GetUserArray("thismonth");
                StatVar.Update("postsrank", "thismonth", array3.ToXml());
            }
            XUser[] array4;
            if (statvars.ContainsKey("today"))
            {
                array4 = statvars["today"].ToXmlEntity<XUser[]>();
            }
            else
            {
                array4 = Stats.GetUserArray("today");
                StatVar.Update("postsrank", "today", array4.ToXml());
            }
            var num = array.Length;
            num = Math.Max(array2.Length, num);
            num = Math.Max(array3.Length, num);
            num = Math.Max(array4.Length, num);
            postsrank = Stats.GetUserRankHtml(array, "posts", num);
            digestpostsrank = Stats.GetUserRankHtml(array2, "digestposts", num);
            thismonthpostsrank = Stats.GetUserRankHtml(array3, "thismonth", num);
            todaypostsrank = Stats.GetUserRankHtml(array4, "today", num);
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetTopicsRank()
        {
            hottopics = Stats.GetHotTopicsHtml();
            hotreplytopics = Stats.GetHotReplyTopicsHtml();
        }

        private void GetForumsRank()
        {
            foreach (String key in forumsrankstats.Keys)
            {
                statvars[key] = forumsrankstats[key] + "";
            }
            CheckLastUpdate("forumsrank");

            var list = Stats.GetForumsRank(statvars, "topics");
            var list2 = Stats.GetForumsRank(statvars, "posts");
            var list3 = Stats.GetForumsRank(statvars, "thismonth");
            var list4 = Stats.GetForumsRank(statvars, "today");
            var num = list.Count;
            num = Math.Max(list2.Count, num);
            num = Math.Max(list3.Count, num);
            num = Math.Max(list4.Count, num);
            topicsforumsrank = Stats.GetForumsRankHtml(list, "topics", num);
            postsforumsrank = Stats.GetForumsRankHtml(list2, "posts", num);
            thismonthforumsrank = Stats.GetForumsRankHtml(list3, "thismonth", num);
            todayforumsrank = Stats.GetForumsRankHtml(list4, "today", num);
            lastupdate = statvars["lastupdate"];
            nextupdate = Utility.ToDateTime(statvars["lastupdate"]).AddMinutes((Double)statscachelife).ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void GetPosts()
        {
            monthpostsofstatsbar = Stats.GetStatsDataHtml("monthposts", monthpostsstats, maxmonthposts);
            daypostsofstatsbar = Stats.GetStatsDataHtml("dayposts", daypostsstats, maxdayposts);
        }

        private void GetClient()
        {
            if (!statstatus) return;

            browserofstatsbar = Stats.GetStatsDataHtml("browser", browserstats, maxbrowser);
            osofstatsbar = Stats.GetStatsDataHtml("os", osstats, maxos);
        }

        private void GetViews()
        {
            if (!statstatus) return;

            weekofstatsbar = Stats.GetStatsDataHtml("week", weekstats, maxweek);
            hourofstatsbar = Stats.GetStatsDataHtml("hour", hourstats, maxhour);
        }

        public String IsChecked(String op)
        {
            if (op == "merge")
            {
                if (DNTRequest.GetString("merge") == "1") return " checked=\"checked\"";

                return "";
            }
            else
            {
                if (!DNTRequest.GetString("types").Contains(op)) return "";

                return " checked=\"checked\"";
            }
        }
    }
}